﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;

namespace Hu.Smart.Core
{
    /// <summary>
    /// 缩略图
    /// </summary>
    public class Thumbnail
    {
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>    
        public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode)
        {
            Image originalImage = Image.FromFile(originalImagePath);

            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case "HW"://指定高宽缩放（可能变形）                
                    break;
                case "W"://指定宽，高按比例                    
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case "H"://指定高，宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case "Cut"://指定高宽裁减（不变形）                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片
            Image bitmap = new System.Drawing.Bitmap(towidth, toheight);

            //新建一个画板
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.White);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                new Rectangle(x, y, ow, oh),
                GraphicsUnit.Pixel);

            try
            {
                //以jpg格式保存缩略图
                bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="mode">生成缩略图的方式</param>    
        public static string MakeThumbnail(Stream stream, int width, int height, string mode)
        {
            string base64 = "";
            Image originalImage = Image.FromStream(stream);

            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case "HW"://指定高宽缩放（可能变形）                
                    break;
                case "W"://指定宽，高按比例                    
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case "H"://指定高，宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case "Cut"://指定高宽裁减（不变形）                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片
            Image bitmap = new System.Drawing.Bitmap(towidth, toheight);

            //新建一个画板
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.White);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                new Rectangle(x, y, ow, oh),
                GraphicsUnit.Pixel);

            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    //以jpg格式保存缩略图
                    bitmap.Save(ms, ImageFormat.Jpeg);
                    base64 = ImageToBase64(ms, ImageFormat.Jpeg);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
                stream.Dispose();
            }
            return base64;
        }

        /// <summary>
        /// Image 转成 base64
        /// </summary>
        /// <param name="fileFullName"></param>
        public static string ImageToBase64(MemoryStream ms, ImageFormat suffixName)
        {
            try
            {
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                return Convert.ToBase64String(arr).Replace("\\r\\n", "").Replace("\\r", "").Replace("\\n", "");
            }
            catch (Exception ex)
            {
                return null;
            }

        }

        public static int readPictureDegree(Stream path)
        {
            int rotate = 0;
            using (var image = System.Drawing.Image.FromStream(path))
            {
                foreach (var prop in image.PropertyItems)
                {
                    if (prop.Id == 0x112)
                    {
                        if (prop.Value[0] == 6)
                            rotate = 90;
                        if (prop.Value[0] == 8)
                            rotate = -90;
                        if (prop.Value[0] == 3)
                            rotate = 180;
                        prop.Value[0] = 1;
                    }
                }
            }
            return rotate;
        }
        public static MemoryStream KiRotate(Stream path, string despath, RotateFlipType rotateFlipType)
        {
            try
            {
                MemoryStream ms = new MemoryStream();
                using (Bitmap bitmap = new Bitmap(path))
                {
                    bitmap.RotateFlip(rotateFlipType);
                    //bitmap.Save(despath);

                    bitmap.Save(ms, ImageFormat.Jpeg);
                }
                return ms;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #region 无损压缩图片
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="sFile">图片的原始路径</param>
        /// <param name="dHeight">缩放后图片的高度</param>
        /// <param name="dWidth">缩放后图片的宽带</param>
        /// <returns></returns>
        public static CompressionResult GetPicThumbnail(Stream sFile, int dWidth, int dHeight, string fileName)
        {
            Image iSource = Image.FromStream(sFile);//从指定的文件创建Image
            ImageFormat tFormat = iSource.RawFormat;//指定文件的格式并获取
            int sW = 0, sH = 0;//记录宽度和高度
            Size tem_size = new Size(iSource.Width, iSource.Height);//实例化size。知矩形的高度和宽度
            if (tem_size.Height > dHeight || tem_size.Width > dWidth)//判断原图大小是否大于指定大小
            {
                sW = dWidth;
                sH = dHeight;
            }
            else//如果原图大小小于指定的大小
            {
                sW = tem_size.Width;//原图宽度等于指定宽度
                sH = tem_size.Height;//原图高度等于指定高度
            }
            Bitmap oB = new Bitmap(dWidth, dHeight);//实例化
            Graphics g = Graphics.FromImage(oB);//从指定的Image中创建Graphics
            g.Clear(Color.White);//设置画布背景颜色
            g.CompositingQuality = CompositingQuality.HighQuality;//合成图像的呈现质量
            g.SmoothingMode = SmoothingMode.HighQuality;//呈现质量
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;//插补模式
                                                                       //开始重新绘制图像
            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
            g.Dispose();//释放资源
                        //保存图片时，设置压缩质量
            EncoderParameters ep = new EncoderParameters();//用于向图像编码器传递值
            long[] qy = new long[1];
            qy[0] = 100;
            EncoderParameter eParm = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParm;
            try
            {
                //获得包含有关内置图像编码器的信息的ImageCodeInfo对象
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageDecoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                string savePath = @"D:\ZipPics\"; //Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);//Environment.CurrentDirectory;
                fileName = Path.Combine(savePath, fileName);
                // 检查图片是否存在，如果存在，则重命名。。

                //if (File.Exists(fileName))
                //{
                //    string ext = Path.GetExtension(fileName);
                //    fileName = fileName.Replace(ext, "-1" + ext);
                //}
                //if (jpegICIinfo != null)
                //{
                //    oB.Save(fileName, jpegICIinfo, ep);
                //}
                //else
                //{
                //    oB.Save(fileName, tFormat);// 已指定格式保存到指定文件
                //}
                try
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        if (jpegICIinfo != null)
                        {
                            oB.Save(ms, jpegICIinfo, ep);
                        }
                        else
                        {
                            oB.Save(ms, tFormat);// 已指定格式保存到指定文件
                        }
                        string newBytes;
                        byte[] zipdata;
                        //using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
                        //{
                        //    newBytes = ByteConversion(fs.Length);
                        //    zipdata = new byte[fs.Length];
                        //    fs.Read(zipdata, 0, zipdata.Length);
                        //    fs.Close();
                        //    fs.Dispose();
                        //}
                        newBytes = ByteConversion(ms.Length);
                        zipdata = new byte[ms.Length];
                        ms.Position = 0;
                        ms.Read(zipdata, 0, zipdata.Length);
                        ms.Close();
                        ms.Dispose();
                        return new CompressionResult() { Success = true, NewBytes = newBytes, NewSize = sW + "×" + sH, FilePath = fileName, FileBytes = zipdata };
                    }
                }
                catch (Exception e)
                {
                    return new CompressionResult() { Success = false };
                }
            }
            catch
            {
                return new CompressionResult() { Success = false };
            }
            finally
            {
                iSource.Dispose();//释放资源
                oB.Dispose();
            }
        }
        #endregion
        // 其它方法
        #region 字节转换成GB、MB和KB
        /// <summary>
        /// 字节转换成GB、MB和KB
        /// </summary>
        /// <param name="KSize"></param>
        /// <returns></returns>
        public static string ByteConversion(long KSize)
        {
            int GB = 1024 * 1024 * 1024;//定义GB的计算常量
            int MB = 1024 * 1024;//定义MB的计算常量
            int KB = 1024;//定义KB的计算常量

            if (KSize / GB >= 1)//如果当前Byte的值大于等于1GB
                return (Math.Round(KSize / (float)GB, 2)).ToString() + " GB";//将其转换成GB
            else if (KSize / MB >= 1)//如果当前Byte的值大于等于1MB
                return (Math.Round(KSize / (float)MB, 2)).ToString() + " MB";//将其转换成MB
            else if (KSize / KB >= 1)//如果当前Byte的值大于等于1KB
                return (Math.Round(KSize / (float)KB, 2)).ToString() + " KB";//将其转换成KGB
            else
                return KSize.ToString() + " 节";//显示Byte值
        }
        #endregion
    }

    #region 生成图片结果
    public class CompressionResult
    {
        public bool Success { get; set; }
        public string NewBytes { get; set; }
        public string NewSize { get; set; }

        public string FilePath { get; set; }

        public byte[] FileBytes { get; set; }
    }

    #endregion

}
